#include "command.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct 
{
	char *name;
	int (*func)(int argc, char *argv[]);
} command_t;

typedef struct L
{
    struct L *next;
    command_t command;
} CLIST;
typedef CLIST* clist_t;

static clist_t base = NULL;

static char* conversion(char *line, int *max)
{
    int len = 0;
    char *s = line;

    while (*s)
    {
        if (*s == ' ') (*max)++;
        len++;
        s++;
    }

    s = (char *)malloc(len + 1);
    if (!s) return NULL;

    memcpy(s, line, len + 1);

    return s;
}

static int analysis(char *line, int max)
{
    char delims[] = " ";
	int argc = 0;
	char* argv[max];
    clist_t l = base;

	argv[argc] = strtok(line, delims);
	while (argv[argc])
	{
		if (++argc >= max) break;
		argv[argc] = strtok(NULL, delims);
	}

    while (l)
    {
        if (!strcmp(argv[0], l->command.name))
        {
            return (l->command.func)(argc, argv);
        }

        l = l->next;
    }

	return -1;
}

int command(const char *line)
{
    int max = 1;
    char* s;
    int ret = 0;

    s = conversion((char *)line, &max);
    if (!s) return -1;
    ret = analysis(s, max);
    free(s);

    return ret;
}

int command_export(const char *name, int (*handle)(int argc, char *argv[]))
{
    clist_t l;
    int size = strlen(name) + 1;

    l = (clist_t)malloc(sizeof(CLIST));
    if (!l) return 0;

    l->command.name = (char *)malloc(size);
    if (!l->command.name)
    {
        free(l);
        return 0;
    }
    memcpy(l->command.name, name, size);
    l->command.func = handle;

    l->next = base;
    base = l;

    return 1;
}

void command_clear(void)
{
    clist_t l = base;

    while (l)
    {
        base = l->next;

        free(l->command.name);
        free(l);

        l = base;
    }
}
